#include <sys/epoll.h>
#include <cstring>
#include "nocopy.hpp"
#include "Log.hpp"

class Epoller
{
    static const int size = 128;
public:
    //1.创建epoll模型
    Epoller()
    {
        _epfd = epoll_create(size);
        if(_epfd > 0)
        {
            lg(INFO, "epoll_create success: %d", _epfd);
        }
        else
        {
            lg(ERROR, "epoll_create error: %s", strerror(errno));
        }
    }

    //2.对_epfd管理的文件描述符集进行等待（事件就绪）
    int EpollerWait(struct epoll_event revents[], int num)
    {
        //-1表示永久阻塞，直到被监视的文件描述符上的某个事件就绪
        int n = epoll_wait(_epfd, revents, num, -1);
        // int n = epoll_wait(_epfd, revents, num, _timeout);
        return n; //有事件就绪文件描述符的个数 
    }

    //3.对_epfd管理的文件描述符进行操作
    int EpollerUpdate(int oper, int sock, int event)
    {
        int n = 0;
        if(oper == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epfd, oper, sock, nullptr);
            if(n != 0) lg(INFO, "epoll_ctl delete error");
        }
        else // EPOLL_CTL_ADD EPOLL_CTL_MOD
        {
            struct epoll_event ev;
            ev.events = event;
            ev.data.fd = sock;
            n = epoll_ctl(_epfd, oper, sock, &ev);
            if(n != 0) lg(ERROR, "epoll_ctl_error!");
        }

        return n;
    }

    ~Epoller()
    {
        if(_epfd) close(_epfd);
    }
private:
    int _epfd; //epoll模型在系统内唯一的一个标识
    int _timeout; //等待事例的超时时间
};